/*
 * AFND.h
 */

#ifndef AFND_H_
#define AFND_H_

#include <set>
#include <map>
#include <iostream>
using namespace std;

class AFND {

    public:
        typedef int Estado;
        const static char LAMBDA = 0;

    public:
        /* NO existe el "AFND vacio" */
        AFND(set<char> &alfabeto); // Constructor para ANY
        AFND(char car, set<char> &alfabeto); // Constructor para UN caracter

        virtual ~AFND();

        AFND* concatenar(AFND& afnd);
        AFND* alternativa(AFND& afnd);

        void hacerOpcional();
        void clausurar();
        void clausurarPositivamente();

        int inicial() const;
        set<char> alfabeto() const;
        set<int> finales() const;
        set<int> estados() const;
        const set<int> sigma(int, char) const;

        set<int> recorrerEstados(set<int>, char) const;

        friend ostream& operator<<(ostream &out, AFND &afnd);

    private:
        set<Estado> alcanzables(Estado) const; // usando LAMBDA
        Estado agregarEstado();
        void agregarTransicion(Estado origen, char caracter, Estado destino);

        class EstadoCaracter {
            public:
                Estado _estado;
                char _caracter;

                EstadoCaracter(int e, char c) : _estado(e), _caracter(c) {}

                friend bool operator<(const EstadoCaracter& eyc1,
                        const EstadoCaracter& eyc2) {
                    return eyc1._estado < eyc2._estado ||
                        (eyc1._estado == eyc2._estado &&
                         eyc1._caracter < eyc2._caracter);
                }

                friend bool operator==(const EstadoCaracter& eyc1,
                        const EstadoCaracter& eyc2) {
                    return eyc1._estado == eyc2._estado &&
                        eyc1._caracter == eyc2._caracter;
                }

        };
        typedef map<EstadoCaracter, set<Estado> > mapaTrans;

        set<char> _alfabeto;
        set<Estado> _estados;
        Estado _inicial;
        set<Estado> _finales;
        mapaTrans _transiciones;
        Estado _ultimo;
};

#endif /* AFND_H_ */
